home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / 7Edit / Pascal Sources / SVEditWindow.p < prev   
Encoding:
Text File  |  1994-02-25  |  31.1 KB  |  1,094 lines  |  [TEXT/MPS ]

  1. {[d-,h-,k+,o=100,q+,r+,rec+,t=2,u+,:+,j=15/20/25/30/35/40/45/50/57/1$]} {Pasmat opts!}
  2.  
  3. {$S Window}
  4.  
  5. UNIT SVEditWindow;
  6. (*
  7.     Version 3.0d8
  8.     
  9.     Copyright © SRL Data 1992, 1993
  10.     
  11.     All rights reserved
  12.     
  13.     Produced by : SRL Data
  14.     Originally Developed for UK.DTS
  15. *)
  16.  
  17.   {The window and text handling routines for the SVEdit example program}
  18.  
  19.     {
  20.         New for 3.0d2
  21.         
  22.         19-Feb-92 : NH    : Implement PrintWindow
  23.                       Change PageStarts to PageEnds
  24.                       Fix out by one in GetPageEnds
  25.                                             
  26.         26-Feb-92    : NH    : Put in final printing implementation
  27.                                         : Fix inThumb scrolling
  28.                                         : Put in kTextOffset to replace kTextMargin for better borders
  29.                                         
  30.         28-Feb-92 : NH  : gCurrSection zapped - Incoming AppleEvents make keeping track
  31.                           via a global very messy. Now check to see when in a section as
  32.                                             required.
  33.                                             
  34.         New for 3.0d3
  35.         
  36.         07-Apr-92 : NH  : PrPicFile added to PrintWindow.
  37.         
  38.          3-Jun-92 : NH  : Fixed bug in DrawPageBreaks (kTextOffset added twice)
  39.                                              Put in progress dialog for printing.
  40.                                             
  41.          7-Jun-92 : NH  : Fixed bug in PrintWindow - pageBounds was a pointer,
  42.                           never initialised so randomly trashed memory when calced
  43.                                             pageBounds for printing
  44.                                             
  45.                                             oldMax,oldValue,theResult - dead vars - removed
  46.         New for 3.0d5
  47.         
  48.         21-Aug-92 : NH :  Added isForNewDoc to NewDocument.
  49.                           Also count of new windows for Untitled #
  50.                                             Eversaved implemented instead of name = untitled
  51.     }
  52.     
  53.   INTERFACE
  54.  
  55.     USES MemTypes, QuickDraw, OSIntf, ToolIntf, Traps, Editions, Printing, SVEditGlobals, SVEditUtils,
  56.  
  57.          SVEditions, SVAppleEvents;
  58.  
  59.     FUNCTION DPtrFromWindowPtr(w: WindowPtr): DPtr;
  60.  
  61.     PROCEDURE MyGrowWindow(w: WindowPtr;
  62.                            p: Point);
  63.  
  64.     PROCEDURE DoZoom(w: WindowPtr;
  65.                      c: INTEGER;
  66.                      p: Point);
  67.  
  68.     PROCEDURE DoContent(theWindow: WindowPtr;
  69.                         theEvent: EventRecord);
  70.  
  71.         PROCEDURE DoActivate(theWindow: WindowPtr;
  72.                                                  activate : BOOLEAN);
  73.  
  74.     PROCEDURE DoUpdate(theDoc: DPtr);
  75.  
  76.     FUNCTION  NewDocument(isForOldDoc:Boolean): DPtr;
  77.  
  78.     PROCEDURE CloseMyWindow(aWindow: WindowPtr);
  79.  
  80.     PROCEDURE ShowSelect(theDoc: DPtr);
  81.  
  82.     PROCEDURE AdjustScrollbars(theDoc: DPtr;
  83.                                needsResize: BOOLEAN);
  84.                                                              
  85.     PROCEDURE GetWinContentRect(theWindow:WindowPtr; VAR r:Rect);
  86.         
  87.     PROCEDURE ResizeWindow(theDoc: DPtr);
  88.  
  89.     PROCEDURE ResizePageSetupForDocument(theDoc: DPtr);
  90.         
  91.         PROCEDURE InvalidateDocument(theDoc: DPtr);
  92.         
  93.         PROCEDURE DrawPageExtras(theDoc:DPtr);
  94.         
  95.         PROCEDURE PrintWindow(theDoc:DPtr; askUser:BOOLEAN);
  96.  
  97.   IMPLEMENTATION
  98.         
  99.         USES Packages;
  100.         
  101.     CONST
  102.       kControlInvisible = 0;
  103.       kControlVisible     = $FF;
  104.       kScrollbarWidth     = 16;
  105.       kScrollbarAdjust     = kScrollbarWidth - 1;
  106.       kScrollTweek           = 2;
  107.             kTextOffset                = 5; 
  108.       kButtonScroll          = 10;
  109.             
  110.             kMaxPages           = 1000; (* Assumes pages > 32 pixels high *)
  111.             
  112.             kHOffset                     = 20; (* Stagger window offsets *)
  113.             kVOffset                     = 20;
  114.             
  115.             kTBarHeight             = 20;
  116.             kMBarHeight             = 20;
  117.             
  118.         TYPE  
  119.             PageEndsArray     = ARRAY [1..kMaxPages] OF INTEGER;
  120.             PPageEnds         = ^PageEndsArray;
  121.             HPageEnds         = ^PPageEnds;
  122.  
  123.       {$S Window}
  124.  
  125.     FUNCTION DPtrFromWindowPtr(w: WindowPtr): DPtr;
  126.  
  127.       BEGIN
  128.         IF w = NIL THEN
  129.           DPtrFromWindowPtr := NIL
  130.         ELSE
  131.           DPtrFromWindowPtr := DPtr(GetWRefCon(w));
  132.       END;
  133.  
  134.     {$S main}
  135.                     
  136.    PROCEDURE AdjustTE(theDoc: DPtr);
  137.  
  138. { Scroll the TERec around to match up to the potentially updated scrollbar
  139.   values. This is really useful when the window resizes such that the
  140.   scrollbars become inactive and the TERec had been previously scrolled. }
  141.  
  142.       VAR
  143.         h : INTEGER;
  144.                 v : INTEGER;
  145.  
  146.       BEGIN
  147.               h := (theDoc^.theText^^.viewRect.left - theDoc^.theText^^.destRect.left) -
  148.                GetCtlValue(theDoc^.hScrollBar) + kTextOffset;
  149.                          
  150.                 v := (theDoc^.theText^^.viewRect.top -
  151.                theDoc^.theText^^.destRect.top) - GetCtlValue(theDoc^.vScrollBar) + kTextOffset;
  152.                                  
  153.         IF (h<>0) OR (v<>0) THEN
  154.                     BEGIN
  155.                         TEScroll(h, v, theDoc^.theText);
  156.                         DrawPageExtras(theDoc);
  157.                     END;
  158.       END;         { AdjustTE }
  159.  
  160.     {$S Main}
  161.  
  162.     PROCEDURE AdjustHV(isVert     : BOOLEAN;
  163.                        control    : ControlHandle;
  164.                            theDoc     : DPtr;
  165.                                              canRedraw: BOOLEAN);
  166.  
  167. {Calculate the new control maximum value and current value, whether it is the horizontal or
  168. vertical scrollbar. The vertical max is calculated by comparing the number of lines to the
  169. vertical size of the viewRect. The horizontal max is calculated by comparing the maximum document
  170. width to the width of the viewRect. The current values are set by comparing the offset between
  171. the view and destination rects. If necessary and we canRedraw, have the control be re-drawn by
  172. calling ShowControl.}
  173.  
  174. {TEStyleSample-vertical max originally used line by line calculations-lineheight was a
  175. constant value so it was easy to figure out what the range should be and pin the value
  176. within range. Now we need to use max and min values in pixels rather than in nlines}
  177.  
  178.       VAR
  179.         docTE          : TEHandle;
  180.         value            : INTEGER;
  181.                 max            : INTEGER;
  182.         oldValue    : INTEGER;
  183.                 oldMax        : INTEGER;
  184.                 sizeRect  : Rect;
  185.  
  186.       BEGIN        { AdjustHV }
  187.               sizeRect := theDoc^.pageSize;
  188.                 docTE    := theDoc^.theText;
  189.         oldValue := GetCtlValue(control);
  190.         oldMax   := GetCtlMax(control);
  191.         IF isVert THEN
  192.           BEGIN
  193.             { new for TEStyleSample }
  194.             max := (TEGetHeight(docTE^^.nLines, 0, docTE)) - (docTE^^.viewRect.bottom -
  195.                    docTE^^.viewRect.top);
  196.  
  197.           END
  198.         ELSE
  199.           max := sizeRect.right - (docTE^^.viewRect.right - docTE^^.viewRect.left);
  200.                 
  201.                 max := max + kTextOffset + kTextOffset; (* Allow over scroll by kTextOffset *)
  202.                 
  203.         IF max < 0 THEN
  204.           max := 0; { check for negative values }
  205.         SetCtlMax(control, max);
  206.         IF isVert THEN
  207.           value := docTE^^.viewRect.top - docTE^^.destRect.top
  208.         ELSE
  209.           value := docTE^^.viewRect.left - docTE^^.destRect.left;
  210.                     
  211.                 value := value + kTextOffset;
  212.                 
  213.         IF value < 0 THEN
  214.           value := 0
  215.         ELSE
  216.           IF value > max THEN
  217.             value := max; { pin the value to within range }
  218.                         
  219.         SetCtlValue(control, value);
  220.         IF canRedraw & ((max <> oldMax) | (value <> oldValue)) THEN
  221.           ShowControl(control); { check to see if the control can be re-drawn }
  222.       END;         { AdjustHV }
  223.  
  224.     {$S Main}
  225.  
  226.     PROCEDURE AdjustScrollValues(theDoc   : DPtr;
  227.                                  canRedraw: BOOLEAN);
  228.  
  229.     { Simply call the common adjust routine for the vertical and horizontal scrollbars. }
  230.  
  231.       BEGIN        { AdjustScrollValues }
  232.         AdjustHV(TRUE,  theDoc^.vScrollBar, theDoc, canRedraw);
  233.         AdjustHV(FALSE, theDoc^.hScrollBar, theDoc, canRedraw);
  234.       END;         { AdjustScrollValues }
  235.  
  236.     PROCEDURE GetTERect(window: WindowPtr;
  237.                         VAR teRect: Rect);
  238.  
  239. {   return a rectangle that is inset from the portRect by the size of
  240.   the scrollbars and a little extra margin. }
  241.  
  242.       BEGIN        { GetTERect }
  243.         teRect := window^.portRect;
  244.         teRect.bottom := teRect.bottom - kScrollbarAdjust; { and for the scrollbars }
  245.         teRect.right := teRect.right   - kScrollbarAdjust;
  246.       END;         { GetTERect }
  247.  
  248.     PROCEDURE AdjustScrollSizes(theDoc: DPtr);
  249.  
  250. { Re-calculate the position and size of the viewRect and the scrollbars.
  251.   kScrollTweek compensates for off-by-one requirements of the scrollbars
  252.   to have borders coincide with the growbox. }
  253.  
  254.       VAR
  255.         teRect        : Rect;
  256.  
  257.       BEGIN        { AdjustScrollSizes }
  258.         GetTERect(theDoc^.theWindow, teRect); {start with teRect}
  259.         WITH theDoc^.theWindow^.portRect DO
  260.           BEGIN                            
  261.             theDoc^.theText^^.viewRect := teRect;
  262.  
  263.             MoveControl(theDoc^.vScrollBar, right - kScrollbarAdjust, - 1);
  264.             SizeControl(theDoc^.vScrollBar, kScrollbarWidth, (bottom - top) - (kScrollbarAdjust -
  265.                         kScrollTweek));
  266.             MoveControl(theDoc^.hScrollBar, - 1, bottom - kScrollbarAdjust);
  267.             SizeControl(theDoc^.hScrollBar, (right - left) - (kScrollbarAdjust - kScrollTweek),
  268.                         kScrollbarWidth);
  269.           END;     { with }
  270.       END;         { AdjustScrollSizes }
  271.  
  272.     {$S Window}
  273.  
  274.     PROCEDURE AdjustScrollbars(theDoc: DPtr;
  275.                                needsResize: BOOLEAN);
  276.  
  277. { Turn off the controls by jamming a zero into their contrlVis fields
  278.   (HideControl erases them and we don't want that). If the controls are to
  279.   be resized as well, call the procedure to do that, then call the procedure
  280.   to adjust the maximum and current values. Finally reset the controls
  281.   to be visible if not in background. }
  282.  
  283.       BEGIN        { AdjustScrollbars }
  284.         WITH theDoc^ DO
  285.           BEGIN
  286.  
  287.             vScrollBar^^.contrlVis := kControlInvisible; { turn them off }
  288.             hScrollBar^^.contrlVis := kControlInvisible;
  289.  
  290.             IF needsResize THEN { move and size if needed }
  291.               AdjustScrollSizes(theDoc);
  292.  
  293.             AdjustScrollValues(theDoc, NOT needsResize); { fool with max and current value }
  294.  
  295.             { Now, restore visibility in case we never had to ShowControl during adjustment }
  296.  
  297.             IF NOT gInBackground THEN
  298.               BEGIN
  299.                 vScrollBar^^.contrlVis := kControlVisible; { turn them on }
  300.                 hScrollBar^^.contrlVis := kControlVisible;
  301.               END
  302.             ELSE
  303.               BEGIN (* make sure they stay invisible *)
  304.                 IF (vScrollBar^^.contrlVis <> 0) THEN
  305.                   HideControl(vScrollBar);
  306.                 IF (hScrollBar^^.contrlVis <> 0) THEN
  307.                   HideControl(hScrollBar);
  308.               END;
  309.           END;
  310.       END;         { AdjustScrollbars }
  311.  
  312.         {$S Window}
  313.         
  314.     PROCEDURE GetWinContentRect(theWindow:WindowPtr; VAR r:Rect);
  315.             BEGIN
  316.                 r        := theWindow^.portRect;
  317.                 r.right  := r.right  - kScrollBarAdjust;
  318.                 r.bottom := r.bottom - kScrollBarAdjust;
  319.             END; (* GetWinContentRect *)
  320.             
  321.         {$S Window}
  322.         
  323.         PROCEDURE InvalidateDocument(theDoc: DPtr);
  324.             VAR oldPort : GrafPtr;
  325.             
  326.             BEGIN
  327.         GetPort(oldPort);
  328.                 SetPort(theDoc^.theWindow);
  329.                 InvalRect(theDoc^.theWindow^.portRect);
  330.                 SetPort(oldPort);
  331.             END;
  332.                         
  333.     PROCEDURE ResizeWindow(theDoc: DPtr);
  334.  
  335.     { Called when the window has been resized to fix up the controls and content }
  336.  
  337.       BEGIN        { ResizeWindow }
  338.         AdjustScrollbars(theDoc, TRUE);
  339.         AdjustTE(theDoc);
  340.                 InvalidateDocument(theDoc);
  341.       END;         { ResizeWindow }
  342.  
  343.     PROCEDURE ResizePageSetupForDocument(theDoc: DPtr);
  344.  
  345.     { Called when the window has been resized to fix up the controls and content }
  346.  
  347.       BEGIN        { ResizePageSetupForDocument }
  348.                 theDoc^.pageSize := theDoc^.thePrintSetup^^.prInfo.rPage;
  349.                 OffsetRect(theDoc^.pageSize, -theDoc^.pageSize.left, -theDoc^.pageSize.top);
  350.             
  351.                 theDoc^.theText^^.destRect.right := theDoc^.theText^^.destRect.left + theDoc^.pageSize.right;
  352.                 
  353.                 TECalText(theDoc^.theText);
  354.                 
  355.                 ResizeWindow(theDoc);
  356.       END;         { ResizePageSetupForDocument }
  357.  
  358.     {$S Main}
  359.  
  360.     PROCEDURE CommonAction(control: ControlHandle;
  361.                            VAR amount: INTEGER);
  362.  
  363. { Common algorithm for setting the new value of a control. It returns the actual amount
  364.   the value of the control changed. Note the pinning is done for the sake of returning
  365.   the amount the control value changed. }
  366.  
  367.       VAR
  368.         value         : INTEGER;
  369.         max           : INTEGER;
  370.  
  371.       BEGIN        { CommonAction }
  372.         value := GetCtlValue(control); { get current value }
  373.         max := GetCtlMax(control); { and max value }
  374.         amount := value - amount;
  375.         IF amount < 0 THEN
  376.           amount := 0
  377.         ELSE
  378.           IF amount > max THEN
  379.             amount := max;
  380.         SetCtlValue(control, amount);
  381.         amount := value - amount; { calculate true change }
  382.       END;         { CommonAction }
  383.  
  384.     {$S Main}
  385.  
  386.     PROCEDURE VActionProc(control: ControlHandle;
  387.                           part: INTEGER);
  388.  
  389. { Determines how much to change the value of the vertical scrollbar by and how
  390.   much to scroll the TE record. }
  391.  
  392.       VAR
  393.         amount        : INTEGER;
  394.         window        : WindowPtr;
  395.         theDoc        : DPtr;
  396.  
  397.       BEGIN        { VActionProc }
  398.         IF part <> 0 THEN
  399.           BEGIN
  400.             window := control^^.contrlOwner;
  401.             theDoc := DPtrFromWindowPtr(window);
  402.             CASE part OF
  403.               inUpButton, inDownButton: amount := 24;
  404.               inPageUp, inPageDown:
  405.                 amount := theDoc^.theText^^.viewRect.bottom - theDoc^.theText^^.viewRect.top; { one
  406.                 page }
  407.             END;   { case }
  408.             IF (part = inDownButton) OR (part = inPageDown) THEN
  409.               amount := - amount; { reverse direction }
  410.             CommonAction(control, amount);
  411.             
  412.                         IF amount <> 0 THEN
  413.               BEGIN
  414.                                 TEScroll(0, amount, theDoc^.theText);
  415.                                 DrawPageExtras(theDoc);
  416.                             END;
  417.           END;     { if }
  418.       END;         { VActionProc }
  419.  
  420.     {$S Main}
  421.  
  422.     PROCEDURE HActionProc(control: ControlHandle;
  423.                           part: INTEGER);
  424.  
  425. { Determines how much to change the value of the horizontal scrollbar by and how
  426.   much to scroll the TE record. }
  427.  
  428.       VAR
  429.         amount        : INTEGER;
  430.         window        : WindowPtr;
  431.         theDoc        : DPtr;
  432.  
  433.       BEGIN        { HActionProc }
  434.         IF part <> 0 THEN
  435.           BEGIN
  436.             window := control^^.contrlOwner;
  437.             theDoc := DPtrFromWindowPtr(window);
  438.             CASE part OF
  439.               inUpButton, inDownButton: amount := kButtonScroll; { a few pixels }
  440.               inPageUp, inPageDown:
  441.                 amount := theDoc^.theText^^.viewRect.right - theDoc^.theText^^.viewRect.left; { a
  442.                 page }
  443.             END;   { case }
  444.             IF (part = inDownButton) OR (part = inPageDown) THEN
  445.               amount := - amount; { reverse direction }
  446.             CommonAction(control, amount);
  447.             IF amount <> 0 THEN
  448.               BEGIN
  449.                                 TEScroll(amount, 0, theDoc^.theText);
  450.                                 DrawPageExtras(theDoc);
  451.                             END;
  452.           END;     { if }
  453.       END;         { HActionProc }
  454.  
  455. {*-----------------------------------------------------------------------
  456.         Name:             ShowSelect
  457.         Purpose:        Scrolls the text selection into view.
  458.     -----------------------------------------------------------------------*}
  459.  
  460.     {$S Window}
  461.  
  462.     PROCEDURE ShowSelect(theDoc: DPtr);
  463.  
  464.       BEGIN
  465.         AdjustScrollbars(theDoc, FALSE);
  466.  
  467.                 (*
  468.                     Let TextEdit do the hard work of keeping the selection visible…
  469.                 *)
  470.  
  471.         TEAutoView(TRUE, theDoc^.theText);
  472.         TESelView(theDoc^.theText);
  473.         TEAutoView(FALSE, theDoc^.theText);
  474.  
  475.                 (*
  476.                     Now rematch the text and the scrollbars…
  477.                 *)
  478.  
  479.         SetCtlValue(theDoc^.hScrollBar,
  480.                     theDoc^.theText^^.viewRect.left - theDoc^.theText^^.destRect.left + kTextOffset);
  481.  
  482.         SetCtlValue(theDoc^.vScrollBar,
  483.                     theDoc^.theText^^.viewRect.top - theDoc^.theText^^.destRect.top  + kTextOffset);
  484.  
  485.       END; (* ShowSelect *)
  486.  
  487.     {$S Window}
  488.  
  489.     PROCEDURE OffsetWindow(aWindow: WindowPtr);
  490.  
  491.       VAR
  492.         theWidth, theHeight, theHScreen, theVScreen: INTEGER;
  493.         xWidth, xHeight, hMax, vMax, wLeft, wTop: INTEGER;
  494.  
  495.       BEGIN
  496.  
  497.         theWidth := aWindow^.portRect.right - aWindow^.portRect.left;
  498.         theHeight := aWindow^.portRect.bottom - aWindow^.portRect.top + kTBarHeight;
  499.  
  500.         theHScreen := screenBits.bounds.right - screenBits.bounds.left;
  501.         theVScreen := screenBits.bounds.bottom - screenBits.bounds.top;
  502.  
  503.         xWidth := theHScreen - theWidth;
  504.         xHeight := theVScreen - (theHeight + kMBarHeight);
  505.  
  506.         hMax := (xWidth DIV kVOffset) + 1;
  507.         vMax := (xHeight DIV KVOffset) + 1;
  508.  
  509.         gWCount := gWCount + 1;
  510.  
  511.         wLeft := (gWCount MOD hMax) * kVOffset;
  512.         wTop := ((gWCount MOD vMax) * KVOffset) + kTBarHeight + kMBarHeight;
  513.  
  514.         MoveWindow(aWindow, wLeft, wTop, FALSE);
  515.       END;
  516.  
  517.     PROCEDURE GetLocalUpdateRgn(window: WindowPtr;
  518.                                 localRgn: RgnHandle);
  519.  
  520.     { Returns the update region in local coordinates }
  521.  
  522.       BEGIN        { GetLocalUpdateRgn }
  523.         CopyRgn(WindowPeek(window)^.updateRgn, localRgn); { save old update region }
  524.         WITH window^.portBits.bounds DO
  525.           OffsetRgn(localRgn, left, top); { convert to local coords }
  526.       END;         { GetLocalUpdateRgn }
  527.  
  528.     {$S Window}
  529.  
  530.     PROCEDURE MyGrowWindow(w: WindowPtr;
  531.                            p: Point);
  532.  
  533.       VAR
  534.         savePort      : GrafPtr;
  535.         theResult     : Longint;
  536.         r             : Rect;
  537.  
  538.       BEGIN
  539.         GetPort(savePort);
  540.         SetPort(w);
  541.         SetRect(r, 80, 80, screenBits.bounds.right, screenBits.bounds.bottom);
  542.         theResult := GrowWindow(w, p, r);
  543.         IF (theResult <> 0) THEN
  544.           IssueSizeWindow(w, LoWord(theResult), HiWord(theResult));
  545.  
  546.         SetPort(savePort);
  547.       END;
  548.  
  549.     {$S Window}
  550.  
  551.     PROCEDURE DoZoom(w: WindowPtr;
  552.                      c: INTEGER;
  553.                      p: Point);
  554.  
  555.       VAR
  556.         savePort      : GrafPtr;
  557.  
  558.       BEGIN
  559.         GetPort(savePort);
  560.         SetPort(w);
  561.         IF TrackBox(w, p, c) THEN
  562.           BEGIN
  563.             EraseRect(w^.portRect);
  564.             IssueZoomCommand(w, c);
  565.           END;
  566.       END;
  567.  
  568.     {$S Window}
  569.  
  570.     PROCEDURE DoContent(theWindow: WindowPtr;
  571.                         theEvent: EventRecord);
  572.  
  573.       VAR
  574.         cntlCode      : INTEGER;
  575.         part          : INTEGER;
  576.         theControl    : ControlHandle;
  577.         savePort      : GrafPtr;
  578.         extend        : BOOLEAN;
  579.         theDoc        : DPtr;
  580.         value         : INTEGER;
  581.  
  582.       BEGIN
  583.         GetPort(savePort);
  584.         SetPort(theWindow);
  585.         theDoc := DPtrFromWindowPtr(theWindow);
  586.  
  587.         GlobalToLocal(theEvent.where);
  588.         cntlCode := FindControl(theEvent.where, theWindow, theControl);
  589.         IF (cntlCode = 0) THEN
  590.           BEGIN
  591.             {only extend the selection if the shiftkey is down}
  592.             extend := (BitAnd(theEvent.modifiers, ShiftKey) <> 0);
  593.  
  594.             IF ptInRect(theEvent.where, theDoc^.theText^^.viewRect) THEN
  595.               TEClick(theEvent.where, extend, theDoc^.theText);
  596.           END
  597.         ELSE
  598.           IF cntlCode = inThumb THEN
  599.             BEGIN
  600.               value := GetCtlValue(theControl);
  601.                             part := TrackControl(theControl, theEvent.where, NIL);
  602.               IF (part <> 0) THEN
  603.                 BEGIN
  604.                   value := value - GetCtlValue(theControl);
  605.                   IF value <> 0 THEN
  606.                                         BEGIN
  607.                                             IF theControl = theDoc^.vScrollBar THEN
  608.                                                 TEScroll(0, value, theDoc^.theText)
  609.                                             ELSE
  610.                                                 TEScroll(value, 0, theDoc^.theText);
  611.                                             DrawPageExtras(theDoc);
  612.                                         END;
  613.                 END; { if }
  614.             END
  615.           ELSE
  616.             IF theControl = theDoc^.vScrollBar THEN
  617.               part := TrackControl(theControl, theEvent.where, @VActionProc)
  618.             ELSE
  619.               part := TrackControl(theControl, theEvent.where, @HActionProc);
  620.  
  621.         SetPort(savePort);
  622.  
  623.       END;
  624.             
  625.         (*$S Window*)
  626.         PROCEDURE DoActivate(theWindow: WindowPtr;
  627.                                                  activate : BOOLEAN);
  628.     
  629.             VAR
  630.                 err                     : OSErr;
  631.                 r                         : Rect;
  632.                 theDoc                : DPtr;
  633.     
  634.             BEGIN
  635.                 IF (theWindow <> NIL) THEN
  636.                     BEGIN
  637.                         theDoc := DPtrFromWindowPtr(theWindow);
  638.                         SetPort(theWindow);
  639.                         DrawGrowIcon(theWindow);
  640.                         GetWinContentRect(theWindow, r);
  641.                         InvalRect(r);
  642.                         IF activate THEN
  643.                             BEGIN
  644.                                 TEActivate(theDoc^.theText);
  645.                                 ShowControl(theDoc^.vscrollBar);
  646.                                 ShowControl(theDoc^.hscrollBar);
  647.                                 DisableItem(myMenus[editM], undoCommand);
  648.                                 err := TEFromScrap;
  649.                                 IF (gWCount = 0) THEN
  650.                                     SetShortMenus;
  651.                             END
  652.                         ELSE
  653.                             BEGIN
  654.                                 TEDeactivate(theDoc^.theText);
  655.                                 HideControl(theDoc^.vscrollBar);
  656.                                 HideControl(theDoc^.hscrollBar);
  657.                                 err := ZeroScrap;
  658.                                 err := TEToScrap;
  659.                             END;
  660.                     END;
  661.             END;
  662.     
  663.     {$S Window}        
  664.         PROCEDURE GetPageEnds(pageHeight: INTEGER;
  665.                                                     theText        : TEHandle;
  666.                               pageBounds: PPageEnds;
  667.                                                     VAR nPages: INTEGER);
  668.                                                         
  669.             VAR pageBase            : INTEGER; (* total pixel offset of pages so far *)
  670.                     thisLine            : INTEGER;
  671.                     lastLine            : INTEGER; 
  672.                     thisPage            : INTEGER; (* Current page being calced *)
  673.                     pageSoFar           : INTEGER; (* Page height used so far by lines on this page *)
  674.                     thisLineH       : INTEGER; (* Height of text line *)
  675.                     pageFirstLine : INTEGER; (* Line # of top of page *)
  676.                     
  677.             BEGIN
  678.               pageBase   := 0;
  679.                 thisLine   := 1;
  680.                 lastLine   := theText^^.nLines;
  681.                 
  682.                 thisPage   := 1;
  683.                 pageSoFar  := 0;
  684.                 WHILE (thisLine <= lastLine) OR (pageSoFar<>0) DO
  685.                     BEGIN
  686.                       pageFirstLine := thisLine;
  687.                         thisLineH     := TEGetHeight(thisLine, thisLine, theText);
  688.                         
  689.                         WHILE (thisLineH+pageSoFar< pageHeight) AND
  690.                               (thisLine <= lastLine) DO
  691.                             BEGIN
  692.                                 pageSoFar := pageSoFar + thisLineH;
  693.                                 thisLine  := thisLine +1;
  694.                             thisLineH := TEGetHeight(thisLine, thisLine, theText);
  695.                             END;
  696.                             
  697.                         IF (pageSoFar<>0) THEN
  698.                             BEGIN
  699.                                 pageBounds^[thisPage] := pageSoFar+pageBase;
  700.                                 pageBase := pageBounds^[thisPage];
  701.                                 thisPage := thisPage + 1;
  702.                           pageSoFar:= 0;
  703.                           END;
  704.                             
  705.                         (*
  706.                             Special case text line taller than page
  707.                         *)
  708.                         
  709.                         IF (thisLine  = pageFirstLine) AND
  710.                            (thisLineH > pageHeight) THEN
  711.                             BEGIN
  712.                               REPEAT
  713.                                   pageBounds^[thisPage] := pageBase+pageHeight;
  714.                                     pageBase   := pageBounds^[thisPage];
  715.                                     thisPage   := thisPage + 1;
  716.                                     thisLineH  := thisLineH - pageHeight;
  717.                                 UNTIL (thisLineH < pageHeight);
  718.                                 pageSoFar := thisLineH; (* Carry bottom of large line to next page *)
  719.                                 thisLine  := thisLine + 1; (* carry xs on as pageSoFar and start measuring next line *)
  720.                             END;
  721.                     END;
  722.                     
  723.                 nPages := thisPage -1;
  724.                 
  725.             END; (* GetPageEnds *)
  726.         
  727.         PROCEDURE DrawPageBreaks(theDoc : DPtr);
  728.             VAR PageEnds   : PageEndsArray;
  729.                 nPages     : INTEGER;
  730.                     ctr        : INTEGER;
  731.                     lineBase   : INTEGER;
  732.                     viewRect   : Rect;
  733.                     pageHeight : INTEGER;
  734.                     
  735.             BEGIN
  736.                 pageHeight := theDoc^.pageSize.bottom - theDoc^.pageSize.top;
  737.                 
  738.                 GetPageEnds(pageHeight,
  739.                                         theDoc^.theText,
  740.                                         @pageEnds,
  741.                                         nPages);
  742.                                             
  743.                 lineBase := theDoc^.theText^^.destRect.top;
  744.                 viewRect := theDoc^.theText^^.viewRect;
  745.  
  746.                 PenPat(gray);
  747.                 FOR ctr := 1 to nPages-1 DO
  748.                     BEGIN
  749.                         MoveTo(viewRect.left, lineBase+PageEnds[ctr]);
  750.                         LineTo(viewRect.right,lineBase+PageEnds[ctr]);
  751.                     END;
  752.                 PenNormal;
  753.             END; (*    DrawPageBreaks *)
  754.             
  755.         PROCEDURE DrawPageExtras(theDoc:DPtr);
  756.             VAR oldPort    : GrafPtr;
  757.                     oldClip         : RgnHandle;
  758.                 rectToClip : Rect;
  759.             
  760.             BEGIN
  761.               GetPort(oldPort);
  762.                 SetPort(theDoc^.theWindow);
  763.                 
  764.             oldClip := NewRgn;
  765.                 GetClip(oldClip);
  766.                 
  767.                 GetWinContentRect(theDoc^.theWindow,rectToClip);
  768.                 ClipRect(rectToClip);
  769.                 
  770.               { draw the borders }
  771.  
  772.         IF theDoc^.showBorders THEN
  773.           ShowSectionBorders(theDoc);
  774.                     
  775.                 { and then the page breaks }
  776.                 
  777.                 DrawPageBreaks(theDoc);
  778.                 
  779.                 SetClip(oldClip);
  780.                 
  781.                 DisposeRgn(oldClip);
  782.                 
  783.                 SetPort(oldPort);
  784.             END; (* DrawPageExtras *)
  785.  
  786.     PROCEDURE DoUpdate(theDoc: DPtr);
  787.  
  788.       VAR
  789.         aWindow       : WindowPtr;
  790.         savePort      : GrafPtr;
  791.         rectClip      : Rect;
  792.  
  793.       BEGIN
  794.         aWindow := theDoc^.theWindow;
  795.         GetPort(savePort);
  796.         SetPort(aWindow);
  797.         BeginUpdate(aWindow);
  798.  
  799.         ClipRect(aWindow^.portRect);
  800.         EraseRect(aWindow^.portRect);
  801.         DrawControls(aWindow);
  802.         DrawGrowIcon(aWindow);
  803.  
  804.                 GetWinContentRect(aWindow, rectClip);
  805.         ClipRect(rectClip);
  806.  
  807.         TEUpdate(aWindow^.portRect, theDoc^.theText);
  808.  
  809.                 DrawPageExtras(theDoc);
  810.                 
  811.         EndUpdate(aWindow);
  812.         ClipRect(aWindow^.portRect);
  813.  
  814.         SetPort(savePort);
  815.       END; (* DoUpdate *)
  816.  
  817.     {$S Window}
  818.  
  819.     FUNCTION NewDocument(isForOldDoc:Boolean): DPtr;
  820.       VAR
  821.         destRect      : Rect;
  822.         viewRect      : Rect;
  823.         vScrollRect   : Rect;
  824.         hScrollRect   : Rect;
  825.         myDoc         : DPtr;
  826.         myWindow      : WindowPtr;
  827.         vScroll       : ControlHandle;
  828.         hScroll       : ControlHandle;
  829.                 theName       : Str255;
  830.                 newNumber     : Str255;
  831.  
  832.       BEGIN
  833.         IF (gWCount = 0) THEN
  834.           SetLongMenus;
  835.  
  836.         myDoc := NIL;
  837.         myWindow := GetNewWindow(windowID, NIL, Pointer( - 1));
  838.         IF (myWindow <> NIL) THEN
  839.           BEGIN
  840.                         IF (NOT isForOldDoc) THEN
  841.                             BEGIN
  842.                                 GetWTitle(myWindow, theName);
  843.                                 gNewDocCount := gNewDocCount+1;
  844.                                 NumToString(gNewDocCount, newNumber);
  845.                                 IF (gNewDocCount>1) THEN
  846.                                     BEGIN
  847.                                         theName := CONCAT(theName,' #');
  848.                                         theName := CONCAT(theName, newNumber);
  849.                                         SetWTitle(myWindow, theName);
  850.                                     END;
  851.                             END;
  852.                     
  853.             OffsetWindow(myWindow);
  854.  
  855.             SetPort(myWindow);
  856.  
  857.             myDoc := DPtr(NewPtr(sizeOf(DocRec)));
  858.  
  859.             SetWRefCon(myWindow, ord4(myDoc));
  860.  
  861.             myDoc^.theWindow := myWindow;
  862.  
  863.             vScrollRect := myWindow^.portRect;
  864.  
  865.             vScrollRect.left  := vScrollRect.right - kScrollBarAdjust;
  866.             vScrollRect.right := vScrollRect.left + kScrollBarWidth;
  867.  
  868.             vScrollRect.bottom := vScrollRect.bottom - 14;
  869.             vScrollRect.top    := vScrollRect.top - 1;
  870.                         
  871.             vScroll := NewControl(myWindow, vScrollRect, '', TRUE, 0, 0, 0, scrollBarProc, 0);
  872.  
  873.             hScrollRect := myWindow^.portRect;
  874.             hScrollRect.top := hScrollRect.bottom - kScrollBarAdjust;
  875.             hScrollRect.bottom := hScrollRect.top + kScrollBarWidth;
  876.  
  877.             hScrollRect.right := hScrollRect.right - 14;
  878.             hScrollRect.left := hScrollRect.left - 1;
  879.             hScroll := NewControl(myWindow, hScrollRect, '', TRUE, 0, 0, 0, scrollBarProc, 0);
  880.  
  881.             myDoc^.vScrollBar := vScroll;
  882.             myDoc^.hScrollBar := hScroll;
  883.             myDoc^.lastID := 0;
  884.             
  885.                         myDoc^.firstSection := NIL;
  886.             myDoc^.lastSection  := NIL;
  887.             myDoc^.numSections  := 0;
  888.                         
  889.             myDoc^.dirty := FALSE;
  890.  
  891.             GetTERect(myWindow, viewRect);
  892.             destRect := viewRect;
  893.  
  894.             myDoc^.theFont := Times;
  895.             myDoc^.theStyle := [];
  896.             myDoc^.theSize := 12;
  897.  
  898.                         myDoc^.thePrintSetup := THPrint(NewHandle(SizeOf(TPrint)));
  899.                         
  900.                         PrOpen;
  901.                         PrintDefault(myDoc^.thePrintSetup);
  902.                         PrClose;
  903.                         
  904.                         myDoc^.pageSize := myDoc^.thePrintSetup^^.prInfo.rPage;
  905.                         OffsetRect(myDoc^.pageSize, -myDoc^.pageSize.left, -myDoc^.pageSize.top);
  906.                         
  907.             destRect.right := destRect.left + myDoc^.pageSize.right;
  908.                         
  909.                         OffsetRect(destRect, kTextOffset, kTextOffset);
  910.                         
  911.             TextFont(Times);
  912.             TextSize(12);
  913.             TextFace([]);
  914.  
  915.             myDoc^.theText := TEStylNew(destRect, viewRect);
  916.  
  917.       {
  918.       SetClikLoop(@AutoScroll, myDoc^.theText);
  919.       }
  920.  
  921.             myDoc^.theFileName := '';
  922.                         myDoc^.everSaved   := FALSE;
  923.             myDoc^.theWindow   := myWindow;
  924.                         
  925.                         myDoc^.showBorders := FALSE;
  926.  
  927.             ResizeWindow(myDoc);
  928.           END;
  929.         NewDocument := myDoc;
  930.       END;
  931.  
  932.     {$S Window}
  933.  
  934.     PROCEDURE CloseMyWindow(aWindow: WindowPtr);
  935.  
  936.       VAR
  937.         aDocument     : DPtr;
  938.         theText       : TEHandle;
  939.  
  940.       BEGIN
  941.         HideWindow(aWindow);
  942.         aDocument := DPtrFromWindowPtr(aWindow);
  943.                 
  944.         theText   := aDocument^.theText;
  945.         TEDispose(theText);
  946.                 
  947.                 IF (aDocument^.thePrintSetup<>NIL) THEN
  948.                     DisposHandle(Handle(aDocument^.thePrintSetup));
  949.                     
  950.         DisposPtr(Ptr(aDocument));
  951.         DisposeWindow(aWindow);
  952.  
  953.         gWCount := gWCount - 1;
  954.  
  955.         {if there are no more windows open, set up the short menus}
  956.         IF gWCount = 0 THEN
  957.           SetShortMenus;
  958.                     
  959.       END;
  960.             
  961.     (*
  962.         Name     : PrintWindow
  963.         Function : Prints the document supplied in theDoc. askUser controls interaction
  964.                    with the user.
  965.                              
  966.                              Uses extra memory equal to the size of the textedit use in the 
  967.                              printed document.
  968.     *)
  969.     
  970.     PROCEDURE PrintWindow(theDoc:DPtr; askUser:BOOLEAN);
  971.         VAR oldPort                 : GrafPtr;
  972.                 printerTE                    : TEHandle;
  973.                 printerPort             : TPPrPort;
  974.                 printView                    : Rect;
  975.                 printerTextStyles : StScrpHandle;
  976.                 pageBounds                : PageEndsArray;
  977.                 nPages                        : INTEGER;
  978.                 oldSelStart                : INTEGER;
  979.                 oldSelEnd                    : INTEGER;
  980.                 pageCtr                        : INTEGER;
  981.                 abort                            : BOOLEAN;
  982.                 rectToClip        : Rect;
  983.                 thePrinterStatus    :    TPrStatus;
  984.                 progressDialog    : DialogPtr;
  985.                 
  986.         BEGIN
  987.             abort := FALSE;
  988.             
  989.             (*
  990.                 Preserve the current port
  991.             *)
  992.             GetPort(oldPort);
  993.             PrOpen;
  994.             
  995.             
  996.             IF askUser THEN
  997.                 abort := NOT PrJobDialog(theDoc^.thePrintSetup);
  998.                 
  999.             IF abort THEN
  1000.                 BEGIN
  1001.                     PrClose;
  1002.                     Exit(PrintWindow);
  1003.                 END;
  1004.             
  1005.             progressDialog := GetNewDialog(1005, NIL, POINTER(-1));
  1006.             
  1007.             DrawDialog(progressDialog);
  1008.             
  1009.             printerPort := PrOpenDoc(theDoc^.thePrintSetup, NIL, NIL);
  1010.             SetPort(GrafPtr(printerPort));
  1011.             
  1012.             (*
  1013.                 Put the window text into the printer port
  1014.             *)
  1015.             
  1016.             printView := theDoc^.thePrintSetup^^.prInfo.rPage;
  1017.             printerTE := TEStylNew(printView, printView);
  1018.  
  1019.             oldSelStart := theDoc^.theText^^.selStart;
  1020.             oldSelEnd   := theDoc^.theText^^.selEnd;
  1021.             
  1022.             TESetSelect(0,theDoc^.theText^^.teLength, theDoc^.theText);
  1023.  
  1024.             printerTextStyles := GetStylScrap(theDoc^.theText);
  1025.  
  1026.             TESetSelect(oldSelStart, oldSelEnd, theDoc^.theText);
  1027.             
  1028.             HLock(Handle(theDoc^.theText^^.hText));
  1029.             
  1030.             TEStylInsert(    Ptr(theDoc^.theText^^.hText^),
  1031.                                         theDoc^.theText^^.teLength,
  1032.                                         printerTextStyles,
  1033.                                         printerTE);
  1034.                                                 
  1035.             HUnLock(Handle(theDoc^.theText^^.hText));
  1036.  
  1037.             (*
  1038.                 Work out the offsets
  1039.             *)
  1040.             printerTE^^.destRect := printView; (* GetPageEnds calls TECalText *)
  1041.             
  1042.             GetPageEnds(printView.bottom-printView.top,
  1043.                                     printerTE,
  1044.                       @pageBounds,
  1045.                                     nPages);
  1046.             
  1047.             TEDeactivate(printerTE);
  1048.  
  1049.             FOR pageCtr := 1 to nPages DO
  1050.                 IF NOT abort THEN
  1051.                     BEGIN
  1052.                         PrOpenPage(printerPort, NIL);
  1053.                                                     
  1054.                         rectToClip := printView;
  1055.                         
  1056.                         IF (pageCtr > 1) THEN
  1057.                             rectToClip.bottom := rectToClip.top + (pageBounds[pageCtr]-pageBounds[pageCtr-1])
  1058.                         ELSE
  1059.                             rectToClip.bottom := rectToClip.top + pageBounds[pageCtr];
  1060.                             
  1061.                         ClipRect(rectToClip);
  1062.                         
  1063.                         IF (PrError = iPrAbort) THEN
  1064.                             abort := TRUE;
  1065.                             
  1066.                         IF not abort THEN
  1067.                             TEUpdate(printView, printerTE);
  1068.                                                 
  1069.                         IF (PrError = iPrAbort) THEN
  1070.                             abort := TRUE;
  1071.                             
  1072.                         PrClosePage(printerPort);
  1073.                         
  1074.                         TEScroll(0,rectToClip.top-rectToClip.bottom, printerTE);
  1075.                     END;
  1076.  
  1077.             TEDispose(printerTE);
  1078.                         
  1079.             PrCloseDoc(printerPort);
  1080.             
  1081.             IF ( theDoc^.thePrintSetup^^.prJob.bJDocLoop = bSpoolLoop ) AND 
  1082.                ( PrError = noErr )  AND
  1083.                  (NOT abort) THEN
  1084.                 PrPicFile( theDoc^.thePrintSetup, NIL, NIL, NIL, thePrinterStatus);
  1085.  
  1086.             PrClose;
  1087.             
  1088.             DisposDialog(progressDialog);
  1089.             
  1090.             SetPort(oldPort);
  1091.             InvalRect(oldPort^.portRect);
  1092.         END;
  1093. END.
  1094.